﻿/*
 * File:   mbport.h
 * Author: aple
 *
 * Created on 2015年8月24日, 下午8:38
 * modify @ 20180804
 * --微调
 */

#ifndef __MBDEF_H
#define	__MBDEF_H

#ifdef	__cplusplus
extern "C" {
#endif

#include "stdint.h"
#include "mbcrc.h"   
#include "dat_quene.h" 

/*****************************************************************************
* @brief   基本数据类型
*****************************************************************************/
	typedef unsigned char       mb_slave_id_type;
	typedef unsigned short      mb_reg_num_type;
	typedef unsigned short      mb_reg_addr_type;
	typedef unsigned short      mb_reg_data_type;

	typedef union {
		uint16_t Val;
		uint16_t uVal;
		int16_t iVal;
		uint16_t uval;
		int16_t ival;
		struct {
			uint8_t LB;
			uint8_t HB;
		} byte;
	} mb_data_type;
	
/*****************************************************************************
* @brief   功能开关
*****************************************************************************/
#ifndef MB_MUL_TASK_EN
#define MB_MUL_TASK_EN							1
#endif

#define MB_BUFF_SIZE							(256 )
#define MB_ERR_CNT_PV							(  5 )
#define SMB_TIMEOUT_MS							(6000)
#define MMB_TIMEOUT_MS							(120 )

#define MB_EVENT_SEND_END						(0x01)
#define MB_EVENT_RCV_END						(0x02)

#define MB_FUN_READ_COILS_ENABLED				(  1 )  //fun: 01
#define MB_FUN_READ_DISCRETE_INPUTS_ENABLED		(  1 )  //fun: 02
#define MB_FUN_READ_REG_ENABLED					(  1 )  //fun: 03    
#define MB_FUN_READ_INPUT_ENABLED				(  1 )  //fun: 04
#define MB_FUN_WRITE_COIL_ENABLED				(  1 )  //fun: 05
#define MB_FUN_WRITE_REG_ENABLED				(  1 )  //fun: 06
#define MB_FUN_WRITE_MULTIPLE_COILS_ENABLED		(  1 )  //fun: 15
#define MB_FUN_WRITE_MULTIPLE_REG_ENABLED		(  1 )  //fun: 16 
#define MB_FUN_W_R_MULTIPLE_REG_ENABLED			(  1 )  //fun: 0x17 

#define MB_REG_COILS_CB_ENABLE					( MB_FUN_READ_COILS_ENABLED + MB_FUN_WRITE_COIL_ENABLED + MB_FUN_WRITE_MULTIPLE_COILS_ENABLED  ) 
#define MB_REG_HOLDING_CB_ENABLE				( MB_FUN_READ_REG_ENABLED + MB_FUN_WRITE_REG_ENABLED + MB_FUN_WRITE_MULTIPLE_REG_ENABLED + MB_FUN_W_R_MULTIPLE_REG_ENABLED )  
#define MB_REG_INPUT_CB_ENABLE					( MB_FUN_READ_INPUT_ENABLED   ) 
#define MB_REG_DISCRETE_CB_ENABLE				( MB_FUN_READ_DISCRETE_INPUTS_ENABLED   )    

#define MB_COIL_ON								0xFF00
#define MB_COIL_OFF								0x0000

#define MB_ERR_CODE								0x80
#define MB_FAULT_CODE1							0x01
#define MB_FAULT_CODE2							0x02
#define MB_FAULT_CODE3							0x03
#define MB_FAULT_CODE4							0x04

#define MB_ERR_NONE								0        // 无错误
#define MB_ERR_NOREG							1        // 寄存器地址错误
#define MB_ERR_DATA								2 
#define MB_ERR_CRC_LRC							3 
#define MB_ERR_FUN_CODE							4
#define MB_ERR_HAL								5
#define MB_ETIMEDOUT							16       

#define MB_SLAVE_ERR_CRC						11
#define MB_SLAVE_ERR_HAL						12
#define MB_SLAVE_ERR_ADDR						13
#define MB_SLAVE_ERR_FUN_CODE					14
#define MB_SLAVE_ERR_DATA						15
#define MB_SLAVE_ERR_FRAME						16
#define MB_SLAVE_ERR_UNKNOWN					127

#define     MB_NULL            (0)

/*****************************************************************************
* @brief   支持的命令列表
*****************************************************************************/
	typedef enum {
		FUN_CODE_NONE = 0,
		FUN_CODE_READ_COILS = 0x01,
		FUN_CODE_READ_DISCRETE = 0x02,
		FUN_CODE_READ_REG = 0x03,
		FUN_CODE_READ_INPUT = 0x04,
		FUN_CODE_WRITE_COIL = 0x05,
		FUN_CODE_WRITE_REG = 0x06,
		FUN_CODE_WRITE_MULTIPLE_COIL = 0x0F,
		FUN_CODE_WRITE_MULTIPLE_REG = 0x10,
		FUN_CODE_WRITE_MASK = 0x16,
		FUN_CODE_W_R_MULTIPLE_REG = 0x17,
		FUN_CODE_READ_SLAVE_ID = 0x2B,
		FUN_GUS_REG_WRITE = 0x80,				// CRC 校验的开启/关闭由配置文件的 0x2C.6 位控制
		FUN_GUS_REG_READ = 0x81,
		FUN_GUS_PV_WRITE = 0x82,
		FUN_GUS_PV_READ = 0x83,
		FUN_GUS_LINE_WRITE = 0x84,
		FUN_GUS_AUTO = 0xEE,					// 无返回数据的自由指令
	} mb_cmd_type;



/*****************************************************************************
* @brief   接收状态定义
*****************************************************************************/
	typedef enum {
		MB_RX_IDLE,								// 接收空闲
		MB_RX_RCV,								// 正在接收
		MB_RX_RCVEND,							// 接收完成
		MB_RX_WAIT,								// 等待接收 - 仅主机
		MB_RX_TIMEOUT							// 等待超时 - 仅主机
	} mb_rcv_st_type;

/*****************************************************************************
* @brief   发送状态定义
*****************************************************************************/
	typedef enum {
		MB_TX_IDLE,								// 发送空闲
		MB_TX_XMIT								// 正在发送
	} mb_snd_st_type;

/*****************************************************************************
* @brief   奇偶校验定义
*****************************************************************************/
	typedef enum {
		MB_PAR_NONE,							// 8N2
		MB_PAR_ODD,								// 8O1
		MB_PAR_EVEN,							// 8E1
		MB_PAR_NONE_1S,							// 8N1
	} mb_parity_type;

/*****************************************************************************
* @brief   寄存器读写
*****************************************************************************/
	typedef enum {
		MB_REG_READ,
		MB_REG_WRITE,
	} mb_reg_mode_type;

/*****************************************************************************
* @brief   工作模式定义
*****************************************************************************/
	typedef enum {
		MB_RTU_MASTER,
		MB_RTU_SLAVE,
		ASCII_MASTER,
		ASCII_SLAVE
	} mb_mode_type;

/*****************************************************************************
* @brief   通用波特率定义
*****************************************************************************/
	typedef enum {
		MB_BAUD_1200 = 0,
		MB_BAUD_2400 = 1,
		MB_BAUD_4800 = 2,
		MB_BAUD_9600 = 3,
		MB_BAUD_19200 = 4,
		MB_BAUD_38400 = 5,
		MB_BAUD_115200 = 6
	} mb_baud_type;

#define mb_baud_tab_create const uint32_t mb_baud_tab[] = {1200, 2400 ,4800, 9600, 19200, 38400, 115200}

	extern const uint32_t mb_baud_tab[];

/*****************************************************************************
* @brief   运行状态
*****************************************************************************/
	typedef union {
		uint32_t st;

		struct {
			uint8_t master_mode;
			uint8_t rtu_mode;
			uint8_t port_st;
			uint8_t connect;
		} bits;
	} mb_run_st_type;

/*****************************************************************************
* @brief   错误状态
*****************************************************************************/
	typedef union {
		uint32_t st;

		struct {
			uint8_t hal;
			uint8_t no_reg;
			uint8_t fun_code;
			uint8_t crc_lrc;
		} bits;
	} mb_err_st_type;

/*****************************************************************************
* @brief   主机命令结构
*****************************************************************************/
	typedef struct
	{
		void *dat;			// 数据指针
		mb_cmd_type cmd;	// 命令功能码
		uint8_t device_id;	// 从站号
		uint16_t dat_addr;	// 数据地址
		uint16_t amount;	// 数据数量
		void(*call_back)(uint8_t cmd_site, uint8_t err_st); //回调
	} mb_cmd_buff_type;

/*****************************************************************************
* @brief   从机回调接口
*****************************************************************************/
	typedef struct {
		uint8_t(*reg_input_cb)(uint8_t * buff, uint16_t addr, uint16_t reg_len);
		uint8_t(*reg_hold_cb)(uint8_t * buff, uint16_t addr, uint16_t reg_len, mb_reg_mode_type rw_mode);
		uint8_t(*reg_discrete_cb)(uint8_t *buff, uint16_t addr, uint16_t coils_len);
		uint8_t(*reg_coils_cb)(uint8_t * buff, uint16_t addr, uint16_t coils_len, mb_reg_mode_type rw_mode);
	} smb_fun_type;

/*****************************************************************************
* @brief   主机管理结构
*****************************************************************************/
	typedef struct {
		com_quene_type dcmd_quene;	// 动态命令队列
		uint8_t err_cnt;			// 错误计数器，发送新命令时自动清除一次
		uint8_t cmd_amount;			// 总缓冲池尺寸
		uint8_t cmd_exe_index;		// 当前处理命令索引
		uint8_t scmd_amount;		// 静态缓冲池尺寸
		uint8_t scmd_exe_index;		// 静态命令处理索引
		mb_cmd_buff_type* pcmdBuff;	// 指令指针 - 指向主机命令缓冲池
#if MB_MUL_TASK_EN > 0 
		void(*mutex_pend)(void);
		void(*mutex_post)(void);
#endif
	} mmb_fun_type;
	
/*****************************************************************************
* @brief   对象接口
*****************************************************************************/
	typedef struct
	{
		void(*rtu_timer_run)(void);
		void(*obj_init)(void);
		void(*mb_poll)(void);
		uint8_t(*os_stc_cmd_req)(uint8_t cmd_site, mb_cmd_buff_type* pcmd);
		uint8_t(*os_dyna_cmd_req)(mb_cmd_buff_type* pcmd);
		uint8_t(*os_stc_cmd_del)(uint8_t cmd_site);
		uint8_t(*stc_cmd_req)(uint8_t cmd_site, mb_cmd_buff_type* pcmd);
		uint8_t(*dyna_cmd_req)(mb_cmd_buff_type* pcmd);
		uint8_t(*stc_cmd_del)(uint8_t cmd_site);
		uint8_t(*cmd_ready_num)(void);
		uint8_t(*cmd_idle_num)(void);
		void(*cmd_clr)(void);
		void(*dgus_poll)(void);
		void(*dgusii_poll)(void);
		void(*vgus_poll)(void);
		void(*vgus_page_set)(uint16_t *page, void(*call_back)(uint8_t, uint8_t));
		void(*vgus_pv_read)(uint16_t *dat, uint16_t addr, uint16_t Len, void(*call_back)(uint8_t, uint8_t));
		void(*vgus_pv_write)(uint16_t *dat, uint16_t addr, uint16_t Len, void(*call_back)(uint8_t, uint8_t));
		//hal layer
		void(*rx_read)(uint8_t dat);
		void(*tx_write)(void(*send)(uint8_t), uint8_t len);
		void(*tx_end)(void);
	} mb_fun_interface_type;

/*****************************************************************************
* @brief   对象结构
*****************************************************************************/
	typedef struct {
		/*运行状态*/
		mb_run_st_type run_st;				// 运行状态
		mb_err_st_type err_st;				// 错误状态
		mb_rcv_st_type rcv_st;				// 接收状态  
		mb_snd_st_type snd_st;				// 发送状态
		uint8_t ascii_st;					// ascii 模式下字节状态
		/*定时器管理*/
		uint8_t rtu_timer_cnt;				// RTU结束判定计时器，用于软件定时
		uint8_t rtu_timer_sv;				// RTU结束判定设定值，用于软件定时
		uint8_t b_rtu_timer_on;				// RTU定时器开启
		uint8_t rtu_rcv_end_keep_cnt;		// 命令延时计时器
		uint8_t rtu_rcv_end_delay_set;		// 命令处理延时设定值-仅主机，用于匹配从站速度
		/*过程参数*/
		uint8_t slave_id;					// 从机id //仅在从模式设置；主模式由内部管理，禁止应用层修改。
		uint16_t timeout_cnt;				// 本机报文发送结束后开始计时//仅供主机 //应在串口ISR中清除
		uint16_t timeout_set;
		uint16_t rcv_cnt;					// 接收数据个数
		uint16_t snd_size;					// 待发送数据个数
		uint16_t snd_cnt;					// 发送过程计数
		/*事件定义*/
		uint16_t os_rtu_end_event;			// RTU结束事件值 预设 //使用OS且用内部管理定时器时使用
		uint16_t os_timeout_event;			// RTU超时事件值 预设 //使用OS且用内部管理定时器时使用
		/*状态监视*/
		uint16_t success_keep_cnt;			// 通信成功保持次数
		uint16_t fail_keep_cnt;				// 通信失败保持次数
		uint16_t success_cnt;				// 通信成功总次数
		uint16_t fail_cnt;					// 通信失败总次数
		uint16_t active_keep_cnt;			// 活动状态计时 //包括 MB_TX_XMIT MB_RX_RCV 
		uint16_t active_keep_max;			// 活动状态计时最大值，用于调试监控
		uint16_t idle_time_cnt;				// 空闲计时器，RX,TX均为IDLE时计时
		uint16_t sucess_none_time_cnt;		// 执行成功后计时，每次成功清除
		uint8_t adu_buff[MB_BUFF_SIZE];		// 数据缓冲

		/*回调函数*/
		void(*adu_send)(void);				// 函数指针 - 发送adu_buff数据到端口，数量由snd_size指示
		void(*os_event_send)(uint16_t event);		// 使用OS时发送事件
		void(*rcv_end_handle_comp)(uint8_t err_st);	// 报文处理结束回调

		/*功能接口*/
		smb_fun_type slave;					// 从机结构
		mmb_fun_type master;				// 主机结构
		mb_cmd_buff_type mcmd_now[2];		// 当前正在处理的命令，仅在接收处理时使用。

		const mb_fun_interface_type *api;	// API封装，选用
	} mb_obj_type;

/*****************************************************************************
* @brief   杂项
*****************************************************************************/
	typedef struct
	{
		uint8_t check_val_old;
		uint8_t release_time;
		uint8_t press_time;
		uint8_t opt_out;
	} mb_gus_keep_key_t;


/*****************************************************************************
* @brief   处理过程
*****************************************************************************/
/*
	从机：
	RX-IDLE&TX-IDLE -> RX-RCV&TX-IDLE -> RX-RCVEND&TX-IDLE -> RX-IDLE&TX-SEND -> RX-IDLE&TX-IDLE

	主机：
	RX-IDLE&TX-IDLE -> RX-RCV&TX-SEND -> RX-RCV&TX-IDLE -> RX-RCVEND&TX-IDLE -> RX-IDLE&TX-IDLE
*/

#ifdef	__cplusplus
}
#endif

#endif	/* __MBDEF_H */

